package org.yourscrum.domain;

import org.springframework.util.Assert;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @author Jettro Coenradie
 */
@Entity
@Table(name = "backlog")
public class Backlog extends AbstractEntity {
    @OneToMany(mappedBy = "backlog", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private List<Story> stories = new ArrayList<Story>();

    public Backlog() {
    }

    public int numberOfStories() {
        return stories.size();
    }


    public Story highestPriorityStory() {
        if (stories.isEmpty()) {
            return null;
        }
        return stories.get(0);
    }

    public List<Story> allAvailableStories() {
        return Collections.unmodifiableList(stories);
    }

    public void planOnTop(Story story) {
        Assert.notNull(story, "The story to be planned cannot be null");
        if (!stories.isEmpty()) {
            story.planBefore(stories.get(0));
        }
        stories.add(0, story);
    }

    public void plan(Story story, PlanType plantype, Story plannedStory) {
        Assert.notNull(story, "The object to be planned cannot be null");
        Assert.notNull(plannedStory, "The object allready planned cannot be null");
        Assert.notNull(plantype, "The PlanType cannot be null");
        Assert.isTrue(stories.contains(plannedStory), "The existing story does not exist in the backlog");

        int indexStory = stories.indexOf(story);
        if (indexStory >= 0) {
            if (indexStory > 0) {
                Story currentPreviousStory = stories.get(indexStory - 1);
                currentPreviousStory.planBefore(story.nextStory());
            }
            stories.remove(indexStory);
        }

        int indexPlannedStory = stories.indexOf(plannedStory);

        if (plantype == PlanType.BEFORE) {
            if (indexPlannedStory > 0) {
                Story oldBeforeStory = stories.get(indexPlannedStory - 1);
                oldBeforeStory.planBefore(story);
            }
            story.planBefore(plannedStory);
        } else {
            plannedStory.planBefore(story);
            if (plannedStory.nextStory() != null) {
                Story oldAfterStory = plannedStory.nextStory();
                story.planBefore(oldAfterStory);
            } else {
                story.planAtEnd();
            }
        }
        if (plantype == PlanType.AFTER) {
            indexPlannedStory++;
        }
        stories.add(indexPlannedStory, story);
    }

    public void planAtBottom(Story story) {
        Assert.notNull(story, "The object to be planned cannot be null");
        if (!stories.isEmpty()) {
            Story lastStory = stories.get(stories.size() - 1);
            lastStory.planBefore(story);
            story.planAtEnd();
        }
        stories.add(story);
    }
}
